package order.dao.impl;

import java.sql.SQLException;
import java.util.List;

import order.dao.IOrderDAO;
import order.model.OpenTable;
import order.model.OrderItem;

import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.springframework.orm.hibernate3.HibernateCallback;

import common.bean.PageInfo;
import common.dao.GenericDAO;
import common.exception.DataAccessException;

public class OrderDAO extends GenericDAO implements IOrderDAO
{

	@Override
	public OpenTable getOpenTable(int orderId) throws DataAccessException
	{
		try
		{
			return (OpenTable)getHibernateTemplate().get(OpenTable.class, orderId);
		}
		catch(Exception e)
		{
			throw new DataAccessException(e);
		}
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<OrderItem> getOrderItems(int orderId)
			throws DataAccessException
	{
		try
		{
			return (List<OrderItem>)getHibernateTemplate().find("from OrderItem oi where oi.orderId=?", orderId);
		}
		catch(Exception e)
		{
			throw new DataAccessException(e);
		}
	}

	@Override
	public int saveOpenTable(OpenTable openTable) throws DataAccessException
	{
		try
		{
			Integer id = (Integer)getHibernateTemplate().save(openTable);
			return (id != null ? id : -1);
		}
		catch(Exception e)
		{
			throw new DataAccessException(e);
		}
	}
	
	@Override
	public void updateOpenTable(OpenTable openTable) throws DataAccessException
	{
		try
		{
			getHibernateTemplate().saveOrUpdate(openTable);
		}
		catch(Exception e)
		{
			throw new DataAccessException(e);
		}
	}

	@Override
	public void saveOrderItems(final List<OrderItem> orderItems)
			throws DataAccessException
	{
		if(orderItems == null || orderItems.size() < 1) return ;
		try
		{
			getHibernateTemplate().execute(new HibernateCallback(){
				@Override
				public Object doInHibernate(Session session)
						throws HibernateException, SQLException
				{
					Transaction ts = session.beginTransaction();
					try{
						for(OrderItem orderItem : orderItems)
						{
							session.saveOrUpdate(orderItem);
						}
						ts.commit();
					}catch(Exception e){
						ts.rollback();
						throw new DataAccessException(e);
					}
					return null;
				}
				
			});
		}
		catch(Exception e)
		{
			throw new DataAccessException(e);
		}
	}

	@Override
	public void deleteOpenTable(final int orderId) throws DataAccessException
	{
		try
		{
			getHibernateTemplate().execute(new HibernateCallback(){
				@Override
				public Object doInHibernate(Session session)
						throws HibernateException, SQLException
				{
					String hql = "delete from OpenTable ot where ot.orderId="+orderId;
					Transaction ts = session.beginTransaction();
					try{
						Query query = session.createQuery(hql);
						query.executeUpdate();
						ts.commit();
					}catch(Exception e){
						ts.rollback();
						throw new DataAccessException(e);
					}
					return null;
				}
				
			});
		}
		catch(Exception e)
		{
			throw new DataAccessException(e);
		}
	}

	@Override
	public void deleteOrderItems(final int orderId) throws DataAccessException
	{
		try
		{
			getHibernateTemplate().execute(new HibernateCallback(){
				@Override
				public Object doInHibernate(Session session)
						throws HibernateException, SQLException
				{
					String hql = "delete from OrderItem oi where oi.orderId="+orderId;
					Transaction ts = session.beginTransaction();
					try
					{
						Query query = session.createQuery(hql);
						query.executeUpdate();
						ts.commit();
					}
					catch(Exception e)
					{
						ts.rollback();
						throw new DataAccessException(e);
					}
					return null;
				}
			});
		}
		catch(Exception e)
		{
			throw new DataAccessException(e);
		}
	}

	@Override
	public void deleteOrderItems(final List<OrderItem> orderItems)
			throws DataAccessException
	{
		if(orderItems == null || orderItems.size() < 1) return ;
		try
		{
			getHibernateTemplate().execute(new HibernateCallback(){
				@Override
				public Object doInHibernate(Session session)
						throws HibernateException, SQLException
				{
					Transaction ts = session.beginTransaction();
					try
					{
						for(OrderItem oi : orderItems)
						{
							session.delete(oi);
						}
						ts.commit();
					}
					catch(Exception e)
					{
						ts.rollback();
						throw new DataAccessException(e);
					}
					return null;
				}
			});
		}
		catch(Exception e)
		{
			throw new DataAccessException(e);
		}
	}

	@Override
	public List<OpenTable> list(PageInfo page) throws DataAccessException
	{
		if(page == null) throw new IllegalArgumentException("parameter page can't be null!");
		
		page.setTotalNum(getTotalOpenTables());
		page.validate();//validate page info
		
		return queryOpenTables(page);
	}
	
	@SuppressWarnings("unchecked")
	private List<OpenTable> queryOpenTables(final PageInfo page)
	{
		List<OpenTable> openTables = (List<OpenTable>) getHibernateTemplate().execute(
				new HibernateCallback(){
				@Override
				public Object doInHibernate(Session session)
						throws HibernateException, SQLException
				{
					List<OpenTable> result = null;
					String hql = "from OpenTable";
					Transaction ts = session.beginTransaction();
					try
					{
						Query query = session.createQuery(hql);
						query.setFirstResult((int)((page.getIndex() - 1) * page.getCount()));
						query.setMaxResults((int)(page.getCount()));
						result = query.list();
						
						ts.commit();
					}
					catch(Exception e)
					{
						ts.rollback();
						throw new DataAccessException(e);
					}
					
					return result;
				}
		});
		
		return openTables;
	}
	
	private long getTotalOpenTables()
	{
		Long totalNum = (Long) getHibernateTemplate().execute(new HibernateCallback(){
			@Override
			public Object doInHibernate(Session session)
					throws HibernateException, SQLException
			{
				Long num = null;
				String hql = "select count(*) from OpenTable";
				Transaction ts = session.beginTransaction();
				try
				{
					Query query = session.createQuery(hql);
					num = (Long)query.list().get(0);
					ts.commit();
				}
				catch(Exception e)
				{
					ts.rollback();
					throw new DataAccessException(e);
				}
				return num;
			}
		});
		return (totalNum != null ? totalNum : -1L);
	}

}
